/**
************************************************************
* @file         gizwits_product.c
* @brief        Gizwits control protocol processing, and platform-related       hardware initialization
* @author       Gizwits
* @date         2017-07-19
* @version      V03030000
* @copyright    Gizwits
*
* @note         机智云.只为智能硬件而生
*               Gizwits Smart Cloud  for Smart Products
*               链接|增值ֵ|开放|中立|安全|自有|自由|生态
*               www.gizwits.com
*
***********************************************************/

#include <stdio.h>
#include <string.h>
#include "hal_key.h"
#include "gizwits_product.h"
#include "common.h"
#include "ringBuffer.h"


#define MAX_PACKAGE_LEN    (sizeof(devStatus_t)+sizeof(attrFlags_t)+20)                 ///< Data buffer maximum length
#define RB_MAX_LEN          (MAX_PACKAGE_LEN*2)     ///< Maximum length of ring buffer



static uint32_t timerMsCount;
uint8_t aRxBuffer;
uint8_t bRxBuffer;
/** User area the current device state structure*/
dataPoint_t currentDataPoint;
extern keysTypedef_t keys;
unsigned int ledms;
unsigned int rs485ms;
unsigned int crczh;
unsigned int UPDATAMS;
unsigned char ktled;
unsigned long zzszygdn;//////整数有功电能
extern float AV, BV, CV, AA, BA, CA, ZYGDN, ZWGDN; ///////////////////放置上传的电压，电流数据。
extern unsigned int AVV, BVV, CVV, AAA, BAA, CAA;
extern unsigned int AW, BW, CW; //////////////////////////////放置上传的功率值
extern float ZYGDN, ZWGDN; /////////////////总有功电能
extern unsigned char zhcs;
extern unsigned char AVH, AVL, BVH, BVL, CVH, CVL, AAH, AAL, BAH, BAL, CAH, CAL, AWH, AWL, BWH, BWL, CWH, CWL, YGDNA, YGDNB, YGDNC, YGDND, YGDNE, YGDNF; /////放置485接收到的数据
unsigned char as, bs, cs;

unsigned char ch[4] = {0x10, 0x12, 0x13, 0x14};
uint8_t RECV_FLAG3;
extern unsigned char uart3_rxbuf[67];


extern rb_t pRb_uart3_rxbuf;			///< Ring buffer structure variable
static uint8_t pRb_uart3_Buf[RB_MAX_LEN];     ///< Ring buffer data cache buffer


extern unsigned char RS485UA3_RXDBUF[16];
extern TIM_HandleTypeDef htim2;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;

/**@} */
/**@name Gizwits User Interface
* @{
*/

/**
* @brief Event handling interface

* Description:

* 1. Users can customize the changes in WiFi module status

* 2. Users can add data points in the function of event processing logic, such as calling the relevant hardware peripherals operating interface

* @param [in] info: event queue
* @param [in] data: protocol data
* @param [in] len: protocol data length
* @return NULL
* @ref gizwits_protocol.h
*/
int8_t gizwitsEventProcess(eventInfo_t *info, uint8_t *gizdata, uint32_t len)
{
    uint8_t i = 0;
    dataPoint_t *dataPointPtr = (dataPoint_t *)gizdata;
    moduleStatusInfo_t *wifiData = (moduleStatusInfo_t *)gizdata;
    protocolTime_t *ptime = (protocolTime_t *)gizdata;

    #if MODULE_TYPE
    gprsInfo_t *gprsInfoData = (gprsInfo_t *)gizdata;
    #else
    moduleInfo_t *ptModuleInfo = (moduleInfo_t *)gizdata;
    #endif

    if((NULL == info) || (NULL == gizdata))
    {
        return -1;
    }

    for(i = 0; i < info->num; i++)
    {
        switch(info->event[i])
        {
            case EVENT_KT:
                currentDataPoint.valueKT = dataPointPtr->valueKT;

//        GIZWITS_LOG("Evt: EVENT_KT %d \n", currentDataPoint.valueKT);
                if(0x01 == currentDataPoint.valueKT)
                {
                    HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
                    GIZWITS_LOG("LED——ON\r\n");
                }
                else
                {
                    HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
                    GIZWITS_LOG("LED——OFF\r\n");
                }

                break;




            case WIFI_SOFTAP:
                break;

            case WIFI_AIRLINK:
                break;

            case WIFI_STATION:
                break;

            case WIFI_CON_ROUTER:

                break;

            case WIFI_DISCON_ROUTER:

                break;

            case WIFI_CON_M2M:

                break;

            case WIFI_DISCON_M2M:
                break;

            case WIFI_RSSI:
//        GIZWITS_LOG("RSSI %d\n", wifiData->rssi);
                break;

            case TRANSPARENT_DATA:
//        GIZWITS_LOG("TRANSPARENT_DATA \n");
                //user handle , Fetch data from [data] , size is [len]
                break;

            case WIFI_NTP:
                GIZWITS_LOG("WIFI_WANGLUO : [%d-%d-%d %02d:%02d:%02d][%d] \r\n", ptime->year, ptime->month, ptime->day, ptime->hour, ptime->minute, ptime->second, ptime->ntp);
                break;

            case MODULE_INFO:
//            GIZWITS_LOG("MODULE INFO ...\n");
                #if MODULE_TYPE
//            GIZWITS_LOG("GPRS MODULE ...\n");
                //Format By gprsInfo_t
                #else
//            GIZWITS_LOG("WIF MODULE ...\n");
                //Format By moduleInfo_t
//            GIZWITS_LOG("moduleType : [%d] \n",ptModuleInfo->moduleType);
                #endif
                break;

            default:
                break;
        }
    }

    return 0;
}

/**
* User data acquisition

* Here users need to achieve in addition to data points other than the collection of data collection, can be self-defined acquisition frequency and design data filtering algorithm

* @param none
* @return none
*/
void userHandle(void)
{
    AVV = AVH << 8; //////////运算A相电压
    AVV = AVV + AVL;
    float AV = (float)AVV / 10;

    BVV = BVH << 8; //////////运算B相电压
    BVV = BVV + AVL;
    float BV = (float)BVV / 10;

    CVV = CVH << 8; //////////运算C相电压
    CVV = CVV + CVL;
    float CV = (float)CVV / 10;

    AAA = AAH << 8; //////////运算A相电流
    AAA = AAA + AAL;
    float AA = (float)AAA / 100;

    BAA = BAH << 8; //////////运算B相电流
    BAA = BAA + BAL;
    float BA = (float)BAA / 100;

    CAA = CAH << 8; //////////运算C相电流
    CAA = CAA + CAL;
    float CA = (float)CAA / 100;

    AW = AWH << 8; //////////运算A相功率
    AW = AW + AWL;

    BW = BWH << 8; //////////运算B相功率
    BW = BW + BWL;

    CW = CWH << 8; //////////运算C相功率
    CW = CW + CWL;

    ch[3] = YGDNA;
    ch[2] = YGDNB;
    ch[1] = YGDNC;
    ch[0] = YGDND;
    zzszygdn = (unsigned long)ch[0] | (unsigned long)ch[1] << 8  |  (unsigned long)ch[2] << 16 | (unsigned long)ch[3] << 24; /////////////运算总有功电能
    float ZYGDN = (float)zzszygdn / 100;

    if(zhcs > 99)
    {
        zhcs = 0;
    }



    if(ledms > 500)
    {
        ledms = 0;
        HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);   ///定时500msLED1改变一次状态
//		 GIZWITS_LOG("WIFI_NTP : [%d-%d-%d %02d:%02d:%02d][%d] \n",ptime->year,ptime->month,ptime->day,ptime->hour,ptime->minute,ptime->second,ptime->ntp);
    }


    if(UPDATAMS > 10000) ///定时60秒上传一次数据
    {

        UPDATAMS = 0;
        zhcs++;
        currentDataPoint.valueAV = AV;    ///上传A相电压
        currentDataPoint.valueBV = BV;    ///上传B相电压
        currentDataPoint.valueCV = CV;    ///上传C相电压
        currentDataPoint.valueAA = AA;    ///上传A相电流
        currentDataPoint.valueBA = BA;    ///上传B相电流
        currentDataPoint.valueCA = CA;    ///上传C相电流
        currentDataPoint.valueAW = AW;    ///上传A相功率
        currentDataPoint.valueBW = BW;    ///上传B相功率
        currentDataPoint.valueCW = CW;    ///上传C相功率
        currentDataPoint.valueDQZYGDN = ZYGDN;   ///上传总有功电能
        currentDataPoint.valueDQZWGDN = zhcs;       ///上传总无功电能
        GIZWITS_LOG("\r\n");
        GIZWITS_LOG("\r\n");
        GIZWITS_LOG("SHUJU[%4d:%4d]: \r\n", CAA, AVV);
        GIZWITS_LOG("\r\n");
        GIZWITS_LOG("\r\n");
    }

}

/**
* Data point initialization function

* In the function to complete the initial user-related data
* @param none
* @return none
* @note The developer can add a data point state initialization value within this function
*/
void userInit(void)
{
    memset((uint8_t*)&currentDataPoint, 0, sizeof(dataPoint_t));
    //初始化缓冲区
    pRb_uart3_rxbuf.rbCapacity = RB_MAX_LEN;		//设置缓冲区容量
    pRb_uart3_rxbuf.rbBuff = pRb_uart3_Buf;			//设置缓冲区地址

    if(0 == rbCreate(&pRb_uart3_rxbuf))
    {
        GIZWITS_LOG("pRb_uart3_rxbuf rbCreate Success \n");
    }
    else
    {
        GIZWITS_LOG("pRb_uart3_rxbuf rbCreate Faild \n");
    }

    currentDataPoint.valueKT = 0;
    currentDataPoint.valueAV = 0;
    currentDataPoint.valueBV = 0;
    currentDataPoint.valueCV = 0;
    currentDataPoint.valueAA = 0;
    currentDataPoint.valueBA = 0;
    currentDataPoint.valueCA = 0;
    currentDataPoint.valueAW = 0;
    currentDataPoint.valueBW = 0;
    currentDataPoint.valueCW = 0;
    currentDataPoint.valueDQZYGDN = 0;
    currentDataPoint.valueDQZWGDN = 0;

}


/**
* @brief Millisecond timing maintenance function, milliseconds increment, overflow to zero

* @param none
* @return none
*/
void gizTimerMs(void)
{
    timerMsCount++;
    UPDATAMS++;
    ledms++;
    rs485ms++;
//	crczh++;
}

/**
* @brief Read millisecond count

* @param none
* @return millisecond count
*/
uint32_t gizGetTimerCount(void)
{
    return timerMsCount;
}

/**
* @brief MCU reset function

* @param none
* @return none
*/
void mcuRestart(void)
{
    __set_FAULTMASK(1);
    HAL_NVIC_SystemReset();
}

/**@} */

#ifdef __GNUC__
    /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
    set to 'Yes') calls __io_putchar() */
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
    /* Place your implementation of fputc here */
    /* e.g. write a character to the USART1 and Loop until the end of transmission */
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
    HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);////////////串口3定向发送
    return ch;
}

/**
  * @brief  Period elapsed callback in non blocking mode
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim == &htim2)
    {
        keyHandle((keysTypedef_t *)&keys);
        gizTimerMs();
    }
}

/**
* @brief Timer TIM3 init function

* @param none
* @return none
*/
void timerInit(void)
{
    HAL_TIM_Base_Start_IT(&htim2);
}

/**
  * @brief  This function handles USART IDLE interrupt.
  */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle)
{
    if(UartHandle->Instance == USART2)
    {
        gizPutData((uint8_t *)&aRxBuffer, 1);

        HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);//开启下一次接收中断
    }

    if(UartHandle->Instance == USART3)
    {
        RECV_FLAG3 = 1;
        HAL_UART_Receive_IT(&huart3, uart3_rxbuf, 67); //开启下一次接收中断 63



        GIZWITS_LOG("USRT3_RXD[%4d:%4d]: \r\n", uart3_rxbuf[7], uart3_rxbuf[8]);
        GIZWITS_LOG("USRT3_CRC[%4d:%4d]: \r\n", uart3_rxbuf[65], uart3_rxbuf[66]);
    }
}
//////////////////////////////
/* USER CODE BEGIN 4 */

//void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
//{
//  /* Prevent unused argument(s) compilation warning */
//  UNUSED(huart);
//  /* NOTE: This function Should not be modified, when the callback is needed,
//           the HAL_UART_TxCpltCallback could be implemented in the user file
//   */
//
//	if(Uart1_Rx_Cnt >= 255)  //溢出判断
//	{
//		Uart1_Rx_Cnt = 0;
//		memset(RxBuffer,0x00,sizeof(RxBuffer));
//
//
//	}
//	else
//	{
//		RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer;   //接收数据转存
//
//		if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
//		{

//			Uart1_Rx_Cnt = 0;
//			memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组
//		}
//	}
//
//	HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断
//}
/* USER CODE END 4 */

///////////////////////////////


/**
* @brief USART init function

* Serial communication between WiFi modules and device MCU
* @param none
* @return none
*/
void uartInit(void)
{
    HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);//开启下一次接收中断
    HAL_UART_Receive_IT(&huart3, (uint8_t *)&bRxBuffer, 67);//开启下一次接收中断
}

/**
* @brief Serial port write operation, send data to WiFi module
*
* @param buf      : buf address
* @param len      : buf length
*
* @return : Return effective data length;-1，return failure
*/
int32_t uartWrite(uint8_t *buf, uint32_t len)
{
    uint8_t crc[1] = {0x55};
    uint32_t i = 0;

    if(NULL == buf)
    {
        return -1;
    }

    for(i = 0; i < len; i++)
    {
        HAL_UART_Transmit_IT(&huart2, (uint8_t *)&buf[i], 1);

        while (huart2.gState != HAL_UART_STATE_READY);//Loop until the end of transmission

        if(i >= 2 && buf[i] == 0xFF)
        {
            HAL_UART_Transmit_IT(&huart2, (uint8_t *)&crc, 1);

            while (huart2.gState != HAL_UART_STATE_READY);//Loop until the end of transmission
        }
    }

    #ifdef PROTOCOL_DEBUG

//    GIZWITS_LOG("MCU2WiFi_SHUJU[%4d:%4d]: \r\n", gizGetTimerCount(), len);
    for(i = 0; i < len; i++)
    {
//        GIZWITS_LOG("%02x ", buf[i]);

        if(i >= 2 && buf[i] == 0xFF)
        {
//            GIZWITS_LOG("%02x ", 0x55);
        }
    }

//    GIZWITS_LOG("\n");
    #endif

    return len;
}

/**
* @brief Get usart a packet of data from the ring buffer
*
* @param [in]  rb                  : Input data address
* @param [out] data                : Output data address
* @param [out] len                 : Output data length
*
* @return : 0,Return correct ;-1，Return failure;-2，Data check failure
*/
static int8_t gizGetOnePacket(rb_t *rb, uint8_t *gizdata, uint16_t *len)
{
    int32_t ret = 0;
    uint8_t sum = 0;
    int32_t i = 0;
    uint8_t tmpData;
    uint8_t tmpLen = 0;
    uint16_t tmpCount = 0;
	
    static uint8_t protocolFlag = 0;
    static uint16_t protocolCount = 0;
    static uint8_t lastData = 0;
    static uint8_t debugCount = 0;
	
    uint8_t *protocolBuff = gizdata;
	
    protocolHead_t *head = NULL;		//头指针

    if((NULL == rb) || (NULL == gizdata) ||(NULL == len))
    {
        GIZWITS_LOG("gizGetOnePacket Error , Illegal Param\n");
        return -1;
    }

    tmpLen = rbCanRead(rb);			//读取已经收到的数据长度
    if(0 == tmpLen)
    {
        return -1;		//没有收到数据
    }

    for(i=0; i<tmpLen; i++)
    {
        ret = rbRead(rb, &tmpData, 1);		//读取数据
                                                                                                                                                                                     if(0 != ret)
        {
            if((0xFF == lastData) && (0xFF == tmpData))
            {
                if(0 == protocolFlag)
                {
                    protocolBuff[0] = 0xFF;
                    protocolBuff[1] = 0xFF;
                    protocolCount = 2;
                    protocolFlag = 1;
                }
                else
                {
                    if((protocolCount > 4) && (protocolCount != tmpCount))
                    {
                        protocolBuff[0] = 0xFF;
                        protocolBuff[1] = 0xFF;
                        protocolCount = 2;
                    }
                }
            }
            else if((0xFF == lastData) && (0x55 == tmpData))
            {
            }
            else
            {
                if(1 == protocolFlag)
                {
                    protocolBuff[protocolCount] = tmpData;
                    protocolCount++;

                    if(protocolCount > 4)
                    {
                        head = (protocolHead_t *)protocolBuff;
                        tmpCount = exchangeBytes(head->len)+4;
                        if(protocolCount == tmpCount)
                        {
                            break;
                        }
                    }
                }
            }

            lastData = tmpData;
            debugCount++;
        }
    }

    if((protocolCount > 4) && (protocolCount == tmpCount))
    {
        sum = gizProtocolSum(protocolBuff, protocolCount);

        if(protocolBuff[protocolCount-1] == sum)
        {
            memcpy(gizdata, protocolBuff, tmpCount);
            *len = tmpCount;
            protocolFlag = 0;

            protocolCount = 0;
            debugCount = 0;
            lastData = 0;

            return 0;
        }
        else
        {
            return -2;
        }
    }

    return 1;
}
